package org.dromara.system.kernel;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.system.domain.*;
import org.dromara.system.domain.bo.OrderRelateBo;
import org.dromara.system.domain.bo.PayGroupTypeQueryBo;
import org.dromara.system.domain.bo.config.ApiConfig;
import org.dromara.system.kernel.channel.AdyenKernel;
import org.dromara.system.domain.bo.aparams.AInnerPayBo;
import org.dromara.system.kernel.channel.PowerKernel;
import org.dromara.system.mapper.PayTypeMapper;
import org.dromara.system.service.IPayOrderLogService;
import org.dromara.system.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 订单内嵌支付核心处理
 */
@RefreshScope
@Service
@RequiredArgsConstructor
public class OrderInnerPayKernel {

    private final PayTypeMapper payTypeMapper;
    private final IPayOrderLogService orderLogService;
    private final AdyenKernel adyenKernel;
    private final PowerKernel powerKernel;
    @Value("${gatewayDomain}")
    public String gatewayDomain;

    /**
     * 内嵌支付
     *
     * @param order      订单
     * @param innerPayBo 内嵌支付参数
     */
    public R<?> innerPay(PayOrder order, AInnerPayBo innerPayBo) {

        //新增一条订单日志
        PayOrderLog log = orderLogService.saveLog(null, order.getOrderId(), order.getOrderNo(), order.getOrderAid(), "发起内嵌支付", JSONObject.toJSONString(innerPayBo, JSONWriter.Feature.WriteMapNullValue), null, System.currentTimeMillis());
        if (log == null) {
            return R.fail("Failed to add order log");
        }

        //获取支付平台
        PayType payType = payTypeMapper.selectById(order.getPayTypeId());

        R<?> result;
        try {
            switch (payType.getCode()) {
                case "adyen" -> //adyen内嵌支付
                    result = adyenKernel.adyenPay(order, innerPayBo, log);
                case "power" -> //power内嵌支付
                    result = powerKernel.powerPay(order, innerPayBo, log);
                case "其他" -> //其他内嵌支付
                    result = R.ok();
                default -> //其他内嵌支付
                    result = R.fail("不支持的内嵌支付");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("Request pay Exception");
        }

        orderLogService.updateLog(log.getLogId(), order.getOrderId(), JSONObject.toJSONString(result), System.currentTimeMillis() - log.getTime());

        return result;
    }

    /**
     * 构建内嵌支付链接
     *
     * @param relateBo 账号配置
     * @param bo       轮询收款账号参数
     * @return 内嵌支付链接
     */
    public String buildInnerLink(OrderRelateBo relateBo, PayGroupTypeQueryBo bo) {

        PayType type = relateBo.getPayType();
        PayAccount account = relateBo.getAccount();
        PayGroupAccount groupAccount = relateBo.getGroupAccount();
        ApiConfig apiConfig = ApiConfig.getConfig(type.getConfig(), account.getApiType());
        ApiConfig.PayMethod method = ApiConfig.getPayMethod(apiConfig, groupAccount.getPayMethod());
        JSONObject actConfig = account.getAccountConfig();

        if (apiConfig == null) {
            return null;
        }
        String plugin = apiConfig.getPlugin();
        if (StringUtils.isEmpty(plugin)) {
            return null;
        }

        //是否直连内嵌方式
        if (method != null && (Objects.equals(method.getInnerType(), 2) || method.getInnerPay())) {
            return buildDirectInnerLink(relateBo.getOrder(), type, account);
        }

        String accountDomain = account.getDomain();
        String baseUrl;
        if (actConfig != null && actConfig.containsKey("innerUrl")) {
            //如果账号配置了内嵌地址，则使用账号配置的地址
            baseUrl = accountDomain + actConfig.getString("innerUrl");
        } else {
            baseUrl = accountDomain + (plugin.endsWith("/") ? plugin : plugin + "/") + "preload";
        }

        String innerUrl = baseUrl + "?timestamp=" + (System.currentTimeMillis() / 1000);


        //如果是stripe的内嵌方式
        if (type.getCode().equals("stripe") && method != null && Objects.equals(method.getValue(), "3")) {
            innerUrl += "&total=" + bo.getTotal() + "&currency=" + bo.getCurrency() + "&country=" + (StringUtils.isEmpty(bo.getCountry()) ? "" : bo.getCountry());

            String sessionId = EncryptUtils.encryptBySm4(account.getAccountId() + "", EncryptUtils.PRIVATE_KEY).replaceAll("=", "");
            innerUrl += "&ao=" + sessionId;

            String str = innerUrl + 1 + JwtUtils.secretStr;
            return innerUrl + "&token=" + EncryptUtils.encryptByMd5(str);
        }

        //其他
        String str = gatewayDomain + innerUrl + JwtUtils.secretStr;
        return innerUrl + "&token=" + EncryptUtils.encryptByMd5(str);
    }

    /**
     * 直连内嵌链接
     *
     * @param type    支付平台
     * @param account 收款账号
     * @return 内嵌链接
     */
    public String buildDirectInnerLink(PayOrder order, PayType type, PayAccount account) {

        ApiConfig apiConfig = ApiConfig.getConfig(type.getConfig(), account.getApiType());

        if (apiConfig == null) {
            return null;
        }
        String plugin = apiConfig.getPlugin();
        if (StringUtils.isEmpty(plugin)) {
            return null;
        }

        String sessionId = EncryptUtils.encryptBySm4(order.getOrderId() + "", EncryptUtils.PRIVATE_KEY);
        String innerUrl = gatewayDomain + plugin + ".html";
        String str = innerUrl + JwtUtils.secretStr;
        return innerUrl + "?token=" + EncryptUtils.encryptByMd5(str) + "&session=" + sessionId;
    }
}
